package cn.anecansaitin.whimsy.common.entity;

import cn.anecansaitin.whimsy.common.register.ModEntities;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.TraceableEntity;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import software.bernie.geckolib.animatable.GeoEntity;
import software.bernie.geckolib.core.animatable.GeoAnimatable;
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.core.animation.AnimatableManager;
import software.bernie.geckolib.core.animation.AnimationController;
import software.bernie.geckolib.core.animation.RawAnimation;
import software.bernie.geckolib.util.GeckoLibUtil;

public class StoneSpike extends Entity implements GeoEntity, TraceableEntity {
    @Nullable
    private final Entity owner;
    private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
    private static final RawAnimation active = RawAnimation.begin()
            .thenPlayAndHold("active");//todo 感觉模型有些小了
    private int lifeTick = 9;

    public StoneSpike(EntityType<StoneSpike> entityType, Level level) {
        super(entityType, level);
        owner = null;
    }

    public StoneSpike(Entity owner, double x, double y, double z, float yRot) {
        super(ModEntities.STONE_SPIKE.get(), owner.level());
        this.owner = owner;
        setPos(x, y, z);
        setYRot(yRot * (180F / (float) Math.PI));
    }

    @Override
    public void tick() {
        super.tick();
        if (level() instanceof ServerLevel level) {
            if (lifeTick == 7) {
                for (LivingEntity entity : level.getEntitiesOfClass(LivingEntity.class, getBoundingBox().inflate(0.2D, 0.0D, 0.2D))) {
                    Entity owner = getOwner();
                    if (entity.isAlive() && !entity.isInvulnerable() && entity != owner) {
                        if (owner == null) {
                            entity.hurt(this.damageSources().magic(), 3.0F);
                        } else {
                            if (!owner.isAlliedTo(entity)) {
                                entity.hurt(this.damageSources().indirectMagic(this, owner), 6.0F);
                            }
                        }
                        //实现一个向上的击飞
                        double strength = 0.4 * (1 - entity.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE));
                        entity.addDeltaMovement(new Vec3(0, strength, 0));
                        entity.hasImpulse = true;
                    }
                }
            }

            lifeTick--;

            if (lifeTick <= 0) {
                discard();
            }
        } else {
            double xSpeed = (this.random.nextDouble() * 2.0D - 1.0D) * 0.3D;
            double ySpeed = 0.3D + this.random.nextDouble() * 0.3D;
            double zSpeed = (this.random.nextDouble() * 2.0D - 1.0D) * 0.3D;
            level().addParticle(ParticleTypes.CRIT, getX(), getY(), getZ(), xSpeed, ySpeed, zSpeed);
        }
    }

    @Override
    protected void defineSynchedData() {

    }

    @Override
    protected void readAdditionalSaveData(CompoundTag pCompound) {

    }

    @Override
    protected void addAdditionalSaveData(CompoundTag pCompound) {

    }

    @Override
    public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
        controllers.add(new AnimationController<GeoAnimatable>(this, "con", 0, (e) -> e.setAndContinue(active)));
    }

    @Override
    public AnimatableInstanceCache getAnimatableInstanceCache() {
        return geoCache;
    }

    @Nullable
    @Override
    public Entity getOwner() {
        return owner;
    }

    public static void summonAtLine(Entity owner, double x, double y, double z, float yRot, int count) {
        if (owner.level() instanceof ServerLevel level) {
            float width = 1f;
            yRot = (float) Math.toRadians(yRot + 90);
            double deltaX = Mth.cos(yRot) * width;
            double deltaZ = Mth.sin(yRot) * width;
            count++;

            for (int i = 1; i < count; i++) {
                level.addFreshEntity(new StoneSpike(owner, x + deltaX * i, y, z + deltaZ * i, yRot));
            }
        }
    }
}
